package mc.support.taobao.api.comm;

import com.alibaba.fastjson.JSONObject;
import com.taobao.api.TaobaoClient;
import com.taobao.api.TaobaoRequest;
import com.taobao.api.TaobaoResponse;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 *
 * @author Lisong
 *
 */
public class TaobaoClientProxy {

    public static TaobaoClient createLoggedTaobaoClient(
            final TaobaoClient client) {
        InvocationHandler handler = new TaobaoClientApiLogged(client);
        return (TaobaoClient) Proxy.newProxyInstance(client.getClass()
                .getClassLoader(), client.getClass().getInterfaces(), handler);
    }

    protected static class TaobaoClientApiLogged implements InvocationHandler {

        private static final String DELEGATE_METHOD_NAME = "execute";

        private TaobaoClient target;

        private final static Logger logger = LoggerFactory.getLogger("ming-apis");

        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            long st = System.currentTimeMillis();
            Object result = null;
            Throwable t = null;
            try {
                result = method.invoke(target, args);
            } catch (Throwable e) {
                t = e.getCause() == null ? e : e.getCause();
                throw t;
            } finally {
                String yn = t == null ? "Y" : "N";
                String expMsg = t == null ? "-" : t.getMessage();
                if (DELEGATE_METHOD_NAME.equals(method.getName())) {
                    // (apiMethodName,YN,xxms)(sessionKey,textParams)(errorCode,msg,subCode,subMsg)(exceptionMsg)
                    st = System.currentTimeMillis() - st;
                    String methodName = "-";
                    String reqSessionKey = "-", reqTextParams = "-";
                    String respErrorCode = "-", respMsg = "-", respSubCode = "-", respSubMsg = "-";

                    if( result != null && result instanceof TaobaoResponse){
                        TaobaoResponse resp = (TaobaoResponse)result;
                        respErrorCode = resp.getErrorCode() == null ? respErrorCode : resp.getErrorCode();
                        respMsg = StringUtils.isEmpty(resp.getMsg()) ? respMsg : resp.getMsg();
                        respSubCode = resp.getSubCode() == null ? respSubCode : resp.getSubCode();
                        respSubMsg = StringUtils.isEmpty(resp.getSubMsg()) ? respMsg : resp.getSubMsg();
                        yn = resp.isSuccess() ? yn : "N";
                    }

                    if (args == null || args.length == 0) {
                        methodName = method.toString();
                    } else {
                        for (Object arg : args) {
                            if (arg instanceof TaobaoRequest) {
                                TaobaoRequest<?> req = (TaobaoRequest<?>) arg;
                                methodName = req.getApiMethodName();
                                reqTextParams = "N".equals(yn) ? JSONObject.toJSONString(req.getTextParams()) : reqTextParams;
                            }else if( arg instanceof String){
                                reqSessionKey = (String)arg;
                            }
                        }
                    }

                    try{
	                    logger.info("[({},{},{}ms)({},{})({},{},{},{})({})]",
	                            new Object[]{methodName, yn, st, reqSessionKey,reqTextParams,respErrorCode,respMsg,respSubCode,respSubMsg,expMsg});
	                    }catch(Exception e ){
	                    	//Ignore the error.
	                    	//测试代码，用来跟踪日志IO error的情况
	                    }
                    }
            }
            return result;
        }

        public TaobaoClientApiLogged(TaobaoClient client) {
            this.target = client;
        }
    }
}
